/*
 * @Descripttion: 提供给恒生登录时交易密码AES128加密的方法
 * 该方法的实现 由恒生方提供，
 * 虽然存在一些跟本地模块重复的方法，比如Md5，Base64等，但为了保障准确兼容性，所以单独使用该文件下的实现方式
 * @Author: yubo
 * @Date: 2022-10-12 09:36:19
 * @LastEditTime: 2022-10-12 10:13:37
 */
#pragma once

#include <string>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/buffer.h>
#include <openssl/aes.h>
#include <openssl/md5.h>

/*密码加密流程：
    1) 密钥串使用传入 auth_id 的 资金账号，并使用 MD5_2 方法做md5加密
    2）调用 Encode() 方法进行加密 注：Encode的关键是使用 openssl 的AES_cbc_encrypt, 并进行base64编码
*/

namespace HST3
{
    constexpr int AES_KEY_LENGTH = 16;

    class PwdEncrypt
    {
    public:
        static bool Decode(const char *pszKey, const char *buffer, size_t length, std::string *res);
        static bool Encode(const char *pszKey, const char *buffer, size_t length, std::string *res);
        static void MD5_2(const std::string &src, unsigned char *md);
        
    private:
        // AES加密pkcs#5填充
        static bool AESEncrypt(const char *pszKey, const char *buffer, size_t length, std::string *res);
        // AES解密pkcs#5填充
        static bool AESDecrypt(const char *pszKey, const char *buffer, size_t length, std::string *res);

        static std::string Base64Encode(const char *buffer, int length, bool newLine = false);
        static std::string Base64Decode(const char *input, int length, bool newLine = false);

        static std::string MD5(const std::string &src);
        static std::string StrToHex(const unsigned char *p, int iLen);
        static void HexToStr(const unsigned char *pHex, unsigned int nHexLen, unsigned char *pBuf, unsigned int &nBufLen);
        
        static bool Encode_2(unsigned char cKeyArr[16], const char *buffer, size_t length, std::string *res);
        static bool AESEncrypt_2(unsigned char cKeyArr[16], const char *buffer, size_t length, std::string *res);
    };
}
